use std;
use sdl2;

pub type Off = i32;
pub type Len = u32;

#[derive(Debug, Copy, Clone, Eq, PartialEq)]
pub struct Pos(pub Off, pub Off);

#[derive(Debug, Copy, Clone, Eq, PartialEq)]
pub struct Dim(pub Len, pub Len);

#[derive(Debug, Copy, Clone, Eq, PartialEq)]
pub struct AABB(pub Off, pub Off, pub Len, pub Len);

pub const MAX_DIM: Dim = Dim(std::u32::MAX, std::u32::MAX);
pub const EMPTY: Dim = Dim(0, 0);
pub const ORIGIN: Pos = Pos(0, 0);

impl Dim {
  pub fn min(a: Dim, b: Dim) -> Self {
    Dim(std::cmp::min(a.0, b.0), std::cmp::min(a.1, b.1))
  }

  pub fn max(a: Dim, b: Dim) -> Self {
    Dim(std::cmp::max(a.0, b.0), std::cmp::max(a.1, b.1))
  }
}


impl AABB {
  pub fn new(pos: Pos, dim: Dim) -> Self {
    AABB(pos.0, pos.1, dim.0, dim.1)
  }

  pub fn pos(&self) -> Pos {
    Pos(self.0, self.1)
  }

  pub fn dim(&self) -> Dim {
    Dim(self.2, self.3)
  }

  pub fn contains(&self, pos: Pos) -> bool {
    pos.0 >= self.0
      && pos.1 >= self.1
      && pos.0 <= self.0 + self.2 as i32
      && pos.1 <= self.1 + self.3 as i32
  }
}

impl From<AABB> for sdl2::rect::Rect {
  fn from(b: AABB) -> sdl2::rect::Rect {
    sdl2::rect::Rect::new(b.0, b.1, b.2, b.3)
  }
}
